use std::ffi::CString;
use std::ptr;

use crate::bdev::BDev;
use crate::syslib::{spdk_bdev_create_bs_dev, spdk_bs_dev};
use err_derive::Error;

#[derive(Debug, Error)]
pub enum BlobBDevError {
    #[error(display = "Could not create blob bdev!: {}", _0)]
    FailedToCreate(String),
}

/// SPDK blob store block device.
///
/// This is a virtual representation of a block device that is exported by the backend.
#[derive(Debug)]
pub struct BlobStoreBDev {
    pub(crate) bs_dev: *mut spdk_bs_dev,
}

pub fn create_new_bs_dev(bdev: &mut BDev, writeable: bool) -> Result<BlobStoreBDev, BlobBDevError> {
    let mut dev = BlobStoreBDev {
        bs_dev: ptr::null_mut(),
    };
    let name = CString::new(bdev.name.clone()).expect("Failed to convert bdev name to CString");
    let err = unsafe {
        spdk_bdev_create_bs_dev(
            name.as_ptr(),
            writeable,
            ptr::null_mut(),
            0,
            None,
            ptr::null_mut(),
            &mut dev.bs_dev,
        )
    };

    if err != 0 {
        return Err(BlobBDevError::FailedToCreate(bdev.name.clone()));
    };

    Ok(dev)
}
